var event = require('../../../core/event');
var util = require('../../../util/index');
var layer = require('../../layer/manager');
var sound = require('../../audio/sound');
var $ = window.$;

/**
 * 撤销和恢复
* */
var _inited = false;
var ret = {
	ACTION:{
		ADD:"add.note",
		DEL:"del.note",
		MOV:"move.note"
	},

    init: function() {
        if (this._inited) {
            return;
        }
        this.ui = null;
        event.bind(event.events.global.undo,"grid_undo",this);
        event.bind(event.events.global.redo,"grid_undo",this);
    },

	release: function() {
		event.unbindByKey('grid_undo');
	},

    setUI : function(ui){
        this.ui = ui;
    },

    onEvent: function(e, param){
        if(e == event.events.global.undo){
            if(param){
                this.doUndoAction(param);
                event.trigger(event.events.note.change);
            }
        }else if(e == event.events.global.redo){
            if(param){
                this.doRedoAction(param);
                event.trigger(event.events.note.change);
            }
        }
    },

    pushRecord : function(rec){
        this.ui.record.push(rec);
        this.ui.record.clearRedoList();
    },

    //传递一个中间状态
    mark: function(stat, arg){
        if(stat == "drag_start"){
            var selectedIds = this.ui.getSelectIds();
            this.draggingNotes = {};
            for(var i = 0; i < selectedIds.length; i++){
                var id = selectedIds[i];
                var note = this.ui.manager.getNote(id);
                this.draggingNotes[id] = util.cloneObject(note);
            }
        }else if(stat == "drag_end"){
            var selectedIds = this.ui.getSelectIds();
            var dragParams = [];
            for(var i = 0; i < selectedIds.length; i++){
                var id = selectedIds[i];
                var note = this.ui.manager.getNote(id);
                var endStat = util.cloneObject(note);
                var startStat = this.draggingNotes[note.id];
                if(!startStat){
                    continue;
                }
                var param = {
                    id : note.id,
                    startStat : startStat,
                    endStat : endStat
                };
                dragParams.push(param);
            }
            if(dragParams.length){
                this.pushRecord({
                    key : this.ACTION.MOV,
                    param : dragParams
                });
            }
        }else if(stat == "drag_cancel"){
            delete this.draggingNotes;
        }else if(stat == "add_start"){
            this.noteEditStatus = "add";
        }else if(stat == "edit_start"){
            this.noteEditStatus = "edit";
            var currNote = arg? this.ui.manager.getNote(arg) : this.ui.pluginEdit.editTarget.note;
            this.editNote = {
                startStat : util.cloneObject(currNote),
                id : currNote.id
            };
        }else if(stat == "edit_end"){
            //添加和编辑音符都会触发edit_end 不同的是add的redo是删除 edit的redo是恢复原样
            var currNote = arg? this.ui.manager.getNote(arg) : this.ui.pluginEdit.editTarget.note;
            if(this.noteEditStatus == "edit"){
                //编辑音符等同于移动 都是音符始末状态的转换
                this.editNote.endStat = util.cloneObject(currNote);
                this.pushRecord({
                    key : this.ACTION.MOV,
                    param : [this.editNote]
                });
            }else{
                this.pushRecord({
                    key : this.ACTION.ADD,
                    param : util.cloneObject(currNote)
                });
            }
            this.noteEditStatus = null;
            this.editNote = null;
        }else if(stat == "before_del"){
            var selectedIds = this.ui.getSelectIds();
            var notes = [];
            if(arg){
                notes.push(this.ui.manager.getNote(arg))
            }else{
                for(var i = 0; i < selectedIds.length; i++){
                    var id = selectedIds[i];
                    var note = this.ui.manager.getNote(id);
                    notes.push(util.cloneObject(note));
                }
            }
            this.pushRecord({
               key : this.ACTION.DEL,
               param : notes
            });
        }
    },

	doUndoAction: function(param){
        var param = util.cloneObject(param);
        var key = param.key;
        var param = param.param;
		if(key == this.ACTION.ADD){
            this.undoAddNote(param);
		}else if(key == this.ACTION.MOV){
            this.undoMoveNote(param);
        }else if(key == this.ACTION.DEL){
            this.undoDelNote(param);
        }
	},
    
    doRedoAction : function (param) {
        var param = util.cloneObject(param);
        var key = param.key;
        var param = param.param;
        if(key == this.ACTION.ADD){
            this.undoDelNote([param]);
        }else if(key == this.ACTION.DEL){
            for(var i=0;i<param.length;i++){
                this.undoAddNote(param[i]);
            }
        }else if(key == this.ACTION.MOV){
            this.undoMoveNote(param, true);
        }
    },

    undoDelNote : function(notes){
        for(var i=0;i<notes.length;i++){
            var note = notes[i];
            this.ui.manager.addNoteWithoutNewId(note);
            var html = this.ui.pluginEdit.addNoteDiv(note);
            if(note.sound){
                note.tid = -1;
                this.ui.pluginEdit.adjustNoteSound(note);
            }
        }
    },

    undoAddNote: function(note){
        if(note.sound && note.tid >= 0){
            sound.removeCell(note.tid);
        }
        this.ui.manager.removeNote(note.id);
        var noteDiv = this.ui.getNoteDiv(note.id);
        $(noteDiv).remove();
    },

    undoMoveNote: function(notes, isRedo){
        var manager = this.ui.manager;
        var ui = this.ui;
        for(var i=0; i<notes.length; i++){
            var note = notes[i];
            var id = note.id;
            var index = manager.findNoteById({id : id});
            var currStat = this.ui.manager.getNote(id);
            var toStat = isRedo ? note.endStat : note.startStat;
            //如果末状态有声音 则应该先删掉
            if(currStat.sound && currStat.tid >= 0){
                sound.removeCell(currStat.tid);
            }
            if(toStat.sound){
                toStat.tid = -1;
                this.ui.pluginEdit.adjustNoteSound(toStat);
            }
            manager.chart.note[index] = toStat;
            var newNote = manager.getNote(id);
            ui.alignNote(newNote, ui.getNoteDiv(id));
        }
    }
};

module.exports = ret;